{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 逻辑回归示例\n",
    "\n",
    "利用TensorFlow v2库实现逻辑回归。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## MNIST数据集概述\n",
    "\n",
    "本示例使用的是MNIST手写数字。 数据集包含60,000个用于训练的示例和10,000个用于测试的示例。 这些数字已进行尺寸规格化，并在固定尺寸的图像（28x28像素）中居中，其值从0到255。\n",
    "\n",
    "在此示例中，每个图像将转换为float32，规格化为[0，1]，并展平为784个特征（28 * 28）的一维数组。\n",
    "\n",
    "![MNIST Dataset](http://neuralnetworksanddeeplearning.com/images/mnist_100_digits.png)\n",
    "\n",
    "More info: http://yann.lecun.com/exdb/mnist/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import absolute_import, division, print_function\n",
    "\n",
    "import tensorflow as tf\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# MNIST数据集参数\n",
    "num_classes = 10 # 0 to 9 数字\n",
    "num_features = 784 # 28*28\n",
    "\n",
    "# 训练参数\n",
    "learning_rate = 0.01  # 学习速率\n",
    "training_steps = 1000\n",
    "batch_size = 256\n",
    "display_step = 50"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 准备MNIST数据.\n",
    "from tensorflow.keras.datasets import mnist\n",
    "\n",
    "(x_train, y_train), (x_test, y_test) = mnist.load_data()\n",
    "# Convert to float32.\n",
    "x_train, x_test = np.array(x_train, np.float32), np.array(x_test, np.float32)\n",
    "# 将图像展平为784个特征的一维矢量（28 * 28）\n",
    "x_train, x_test = x_train.reshape([-1, num_features]), x_test.reshape([-1, num_features])\n",
    "# 将图像值从[0，255]标准化为[0，1]\n",
    "x_train, x_test = x_train / 255., x_test / 255."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用tf.data API随机打乱和批处理数据\n",
    "train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))\n",
    "train_data = train_data.repeat().shuffle(5000).batch(batch_size).prefetch(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Weight of shape [784, 10], the 28*28 image features, and total number of classes.\n",
    "W = tf.Variable(tf.ones([num_features, num_classes]), name=\"weight\")\n",
    "# Bias of shape [10], the total number of classes.\n",
    "b = tf.Variable(tf.zeros([num_classes]), name=\"bias\")\n",
    "\n",
    "# 逻辑回归 (Wx + b).\n",
    "def logistic_regression(x):\n",
    "    # 应用softmax将对数归一化为概率分布\n",
    "    return tf.nn.softmax(tf.matmul(x, W) + b)\n",
    "\n",
    "# 交叉熵损失函数\n",
    "def cross_entropy(y_pred, y_true):\n",
    "    # Encode label to a one hot vector.\n",
    "    y_true = tf.one_hot(y_true, depth=num_classes)\n",
    "    # Clip prediction values to avoid log(0) error.\n",
    "    y_pred = tf.clip_by_value(y_pred, 1e-9, 1.)\n",
    "    # Compute cross-entropy.\n",
    "    return tf.reduce_mean(-tf.reduce_sum(y_true * tf.math.log(y_pred), 1))\n",
    "\n",
    "# Accuracy metric.\n",
    "def accuracy(y_pred, y_true):\n",
    "    # Predicted class is the index of highest score in prediction vector (i.e. argmax).\n",
    "    correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.cast(y_true, tf.int64))\n",
    "    return tf.reduce_mean(tf.cast(correct_prediction, tf.float32))\n",
    "\n",
    "# Stochastic gradient descent optimizer.\n",
    "optimizer = tf.optimizers.SGD(learning_rate)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def run_optimization(x, y):\n",
    "    # Wrap computation inside a GradientTape for automatic differentiation.\n",
    "    with tf.GradientTape() as g:\n",
    "        pred = logistic_regression(x)\n",
    "        loss = cross_entropy(pred, y)\n",
    "\n",
    "    # Compute gradients.\n",
    "    gradients = g.gradient(loss, [W, b])\n",
    "    \n",
    "    # Update W and b following gradients.\n",
    "    optimizer.apply_gradients(zip(gradients, [W, b]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step: 50, loss: 1.864911, accuracy: 0.691406\n",
      "step: 100, loss: 1.523811, accuracy: 0.781250\n",
      "step: 150, loss: 1.398870, accuracy: 0.757812\n",
      "step: 200, loss: 1.200829, accuracy: 0.804688\n",
      "step: 250, loss: 1.049814, accuracy: 0.820312\n",
      "step: 300, loss: 0.991233, accuracy: 0.800781\n",
      "step: 350, loss: 0.925867, accuracy: 0.847656\n",
      "step: 400, loss: 0.912035, accuracy: 0.824219\n",
      "step: 450, loss: 0.721192, accuracy: 0.878906\n",
      "step: 500, loss: 0.781742, accuracy: 0.820312\n",
      "step: 550, loss: 0.717376, accuracy: 0.847656\n",
      "step: 600, loss: 0.730978, accuracy: 0.847656\n",
      "step: 650, loss: 0.711157, accuracy: 0.859375\n",
      "step: 700, loss: 0.634577, accuracy: 0.855469\n",
      "step: 750, loss: 0.689660, accuracy: 0.867188\n",
      "step: 800, loss: 0.655194, accuracy: 0.875000\n",
      "step: 850, loss: 0.645942, accuracy: 0.859375\n",
      "step: 900, loss: 0.622855, accuracy: 0.843750\n",
      "step: 950, loss: 0.552879, accuracy: 0.902344\n",
      "step: 1000, loss: 0.570191, accuracy: 0.863281\n"
     ]
    }
   ],
   "source": [
    "# Run training for the given number of steps.\n",
    "for step, (batch_x, batch_y) in enumerate(train_data.take(training_steps), 1):\n",
    "    # Run the optimization to update W and b values.\n",
    "    run_optimization(batch_x, batch_y)\n",
    "    \n",
    "    if step % display_step == 0:\n",
    "        pred = logistic_regression(batch_x)\n",
    "        loss = cross_entropy(pred, batch_y)\n",
    "        acc = accuracy(pred, batch_y)\n",
    "        print(\"step: %i, loss: %f, accuracy: %f\" % (step, loss, acc))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Accuracy: 0.870300\n"
     ]
    }
   ],
   "source": [
    "# 在验证集上测试模型\n",
    "pred = logistic_regression(x_test)\n",
    "print(\"Test Accuracy: %f\" % accuracy(pred, y_test))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model prediction: 7\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model prediction: 2\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model prediction: 1\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model prediction: 0\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model prediction: 4\n"
     ]
    }
   ],
   "source": [
    "# 从验证集预测5张图像\n",
    "n_images = 5\n",
    "test_images = x_test[:n_images]\n",
    "predictions = logistic_regression(test_images)\n",
    "\n",
    "# 显示图像和模型预测\n",
    "for i in range(n_images):\n",
    "    plt.imshow(np.reshape(test_images[i], [28, 28]), cmap='gray')\n",
    "    plt.show()\n",
    "    print(\"Model prediction: %i\" % np.argmax(predictions.numpy()[i]))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
